﻿#region Copyright 2011 Mike Goatly
// This source is subject to the the MIT License (MIT)
// All rights reserved.
#endregion

namespace VS2010MethodIndexer
{
    #region Using Statements
    using System;
    using System.ComponentModel;
    using System.Linq;
    using System.Reflection;
    using System.Windows;
    using System.Windows.Controls;
    using Lifti;

    #endregion

    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class Window1 : Window
    {
        /// <summary>
        /// The index.
        /// </summary>
        private FullTextIndex<MethodInfo> index;

        /// <summary>
        /// Initializes a new instance of the <see cref="Window1"/> class.
        /// </summary>
        public Window1()
        {
            this.InitializeComponent();

            this.index = new FullTextIndex<MethodInfo>();
            this.index.WordSplitter = new PascalCaseWordSplitter();
        }

        /// <summary>
        /// Raises the <see cref="E:System.Windows.FrameworkElement.Initialized"/> event. This method is invoked whenever <see cref="P:System.Windows.FrameworkElement.IsInitialized"/> is set to true internally.
        /// </summary>
        /// <param name="e">The <see cref="T:System.Windows.RoutedEventArgs"/> that contains the event data.</param>
        protected override void OnInitialized(EventArgs e)
        {
            base.OnInitialized(e);

            this.textBox1.Text = "Indexing all loaded assemblies...";
            this.textBox1.IsEnabled = false;

            BackgroundWorker worker = new BackgroundWorker();
            worker.DoWork += (s, ea) => this.IndexAssemblies();
            worker.RunWorkerCompleted += (s, ea) =>
                {
                    this.textBox1.Text = String.Empty;
                    this.textBox1.IsEnabled = true;
                    this.textBox1.TextChanged += this.TextBox1_TextChanged;
                };

            worker.RunWorkerAsync();
        }

        /// <summary>
        /// Handles the TextChanged event of the TextBox1 control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.Controls.TextChangedEventArgs"/> instance containing the event data.</param>
        private void TextBox1_TextChanged(object sender, TextChangedEventArgs e)
        {
            if (this.textBox1.Text.Length == 0)
            {
                this.listBox1.ItemsSource = null;
            }
            else
            {
                this.listBox1.ItemsSource = (from m in this.index.Search(this.textBox1.Text)
                                             orderby m.Name
                                             orderby m.DeclaringType.Name
                                             select m).ToArray();
            }
        }

        /// <summary>
        /// Indexes the assemblies loaded in the current domain.
        /// </summary>
        private void IndexAssemblies()
        {
            var methods = from a in AppDomain.CurrentDomain.GetAssemblies()
                          from t in a.GetTypes()
                          where !t.IsAbstract && t.IsClass && !t.IsNotPublic && !t.IsNested
                          from m in t.GetMethods()
                          where !m.IsSpecialName && m.DeclaringType == t
                          select m;

            this.index.Index(methods.Distinct(), m => m.Name);
        }
    }
}
